const axios = require('axios');
const path = require("path");
const mimeType = require('mime-types');
const fs = require('fs');
const headersC = {
    headers:{
        "Host": "apif.bjjnts.cn",
        "Origin": "https://www.bjjnts.cn",
        "Accept": "application/json, text/plain, */*",
    },
}

const API = {
    LOGIN: "https://apif.bjjnts.cn/account/login",
    STUDY: "https://apif.bjjnts.cn/student-center/study",
    UNIT_INFO: "https://apif.bjjnts.cn/course-units/",
    UNIT_LIST: "https://apif.bjjnts.cn/courses/test-preview",
    STUDIES: "https://apif.bjjnts.cn/studies",
    FACE: "https://apif.bjjnts.cn/supervises",
    CODE: "https://apif.bjjnts.cn/supervises/code",
    SMART_CODE: "https://apif.bjjnts.cn/supervises/smart-new"
}
function wait(ms) {
    return new Promise(resolve =>setTimeout(() =>resolve(), ms * 1000));
}
function getBJ(url, headers) {
    // return new Promise((res , rej) => {
    //     let xml = new XMLHttpRequest();
    //     let param = '';
    //     xml.onreadystatechange = function () {
    //         if(xml.status == 200 && xml.readyState == 4){
    //             res(JSON.parse(xml.responseText))
    //         }
    //     }
    //     xml.open('get',url, false);
    //     if(headers && headers.headers){
    //         for(let i in headers.headers){
    //             xml.setRequestHeader(i, headers.headers[i]);
    //         }
    //     }
    //
    //     xml.send()
    // })
    return axios.get(url, headers)
        .catch(e=>{
        return Promise.resolve({code:999, msg: '挂了',response:e.response})
    })
}

function postBJ(url, param, headers) {
    if(!headers){
        headers = headersC
    }

    return axios.post(url,param,headers).catch(e=>{
        return Promise.resolve({code:999, msg: '挂了',response:e.response})
    })
}


/** 京训钉 登录 */
function start(user, logger) {
    this.userLoginInfo = user;
    this.logger = logger
    // 启动登录
    this.login().then(res=>{
        console.log(res);
    })
}

start.prototype = {
    userLoginInfo:null,
    userInfo:null,
    token:null,
    learnIndex:0,
    unitList:[],
    logger:null,
    async login(){
       let res = await postBJ(API.LOGIN,this.userLoginInfo)
        if(res.code){
            console.log(res.msg);
            return false
        }
        // 赋值 token
        this.token = res.data.access_token;
        this.userInfo = res.data
        this.logs(`登录成功`)
        this.study();
        // this.getFace();
        // this.testAPI();
    },
    getHeaders(url){
        let obj = {
            headers :{
                ...headersC.headers,
                "Content-Type": "application/json",
            }
        }
        if(this.token){
            obj.headers.Authorization = "Bearer " + this.token;
        }
        if(url){
            obj.headers.Referer = url
        }
        return obj
    },
    async study(){
        let _this = this;
        this.logs(`开始获取章节信息`)
       let res = await getBJ(API.STUDY, this.getHeaders())
        if(res.code){
            console.log(res.msg);
            return false
        }
        let courseList = res.data[0].courseMap;
        // 清空章节列表
        this.unitList = [];
        for(let i = 0 ; i < courseList.length ; i ++){
            let classId = courseList[i].class_id;
            let courseId = courseList[i].course_id;
            let coursePar = courseList[i].course.title;
            let res = await this.getUnitList(classId, courseId)
            if(res.code){
                console.log(res.msg);
                return false
            }
            let length = 0;
            let unitList = res.data.course;
            while (unitList[length]){
                let unitLength = 0
                let units = unitList[length].units || []
                if(unitList[length].sections){
                    units = units.concat(unitList[length].sections)
                }
                async function getUnitInfoS(unit){
                    let res1 = await _this.getUnitInfo(courseId,classId,unit.id)
                    let unitInfo = res1.data
                    return {
                        'class_id'      : classId,
                        'course_id'     : unitInfo['video']['course_id'],
                        'unit_id'       : unitInfo['video']['unit_id'],
                        'video_id'      : unitInfo['video']['id'],
                        'time'          : unitInfo['video']['time'],
                        'progress_time' : unitInfo['progress_time'],
                        'unit_title' : unitInfo['title'],
                        'course_title': coursePar,
                    }
                }
                while (units && units[unitLength]){
                    // 存在下级菜单
                    let unit = units[unitLength]
                    if(unit.units){
                        let unites = unit.units;
                        let unitLength = 0;
                        while (unites[unitLength]){
                            let units = unites[unitLength];
                            let obj = await getUnitInfoS(units)
                            this.logs(`课程名字--${coursePar}---获取单元--${obj['unit_title']}`)
                            this.unitList.push(obj);
                            unitLength++
                        }
                    }else {
                        let obj = await getUnitInfoS(unit)
                        this.logs(`课程名字--${coursePar}---获取单元--${obj['unit_title']}`)
                        this.unitList.push(obj);
                    }
                    ++ unitLength
                }
                ++ length
            }
        }
        this.logs(`章节信息获取完毕`)
        await this.startLearn();
    },
    async getUnitList(class_id, course_id ){
        let param = this.getHeaders();
        param.params = {
            course_id,
            class_id
        }
        return await getBJ(API.UNIT_LIST, param)
    },
    async studies($classId, $courseId, $unitId, $videoId, $time, $isEnd = false){
        let $url = API.STUDIES + '?video_id=' + $videoId + '&u=' + this.userInfo.id + '&time=' + $time + '&unit_id=' + $unitId + '&class_id=' + $classId;
        if ($time == 0) {
            $url += '&start=1';
        }
        // 结束学习
        if ($isEnd) {
            $url += '&end=1';
        }
        let url = `https://www.bjjnts.cn/study/video?course_id=${$courseId}&unit_id=${$unitId}&class_id=${$classId}`
        let res = await postBJ($url, {}, this.getHeaders(url))
        if(res.code){
            // 如果是请求 403 等待 1分钟后再次请求, 否则就是 校验规则
            if(res.response.data.code == 3002){
                this.logs(JSON.stringify(res.response.data));
                await wait(60);
                // 再次请求查看是否成功
                return await this.studies($classId, $courseId, $unitId, $videoId, $time, $isEnd)
            }
        }
        let code = (res.data || {}).code
        if(res.response && res.response.data){
            code = res.response.data.code
            this.logs(`--上传日志---${JSON.stringify(res.response.data)}`);
        }
        this.logs(`--课程名字----${url}---状态码--${code}`)
        this.logs(`--上传日志---${JSON.stringify(res.data)}`);
        let _this = this;
        switch (code){
            // 人机验证
            case 2002:
                async function poolApi(){
                    let res2 = await getBJ(API.CODE,_this.getHeaders());
                    let res1 = await getBJ("http://10.10.18.245:8888/digit/recognition/get?imageBase64="+res2.data)
                    let res = await postBJ(API.SMART_CODE, {
                        class_id: $classId,
                        code: res1.data.result,
                        course_id: $courseId,
                        unit_id: $unitId,
                    },_this.getHeaders())
                    // 如果图形验证码错误
                    if(res.code){
                        if(res.response.code == 4001){
                            return await poolApi()
                        }
                    }
                    return res
                }
                res = await poolApi()
                break;
            // 人脸识别
            case 2003:
                res = await this.getFace($classId, $courseId, $unitId);
                if(res.code){
                    return false
                }
                break;
        }
        return res
    },
    async getFace(class_id, course_id, unit_id){
        let filePath = path.resolve(this.userLoginInfo.image); // 原始文件地址
        let fileMimeType = mimeType.lookup(filePath); // 获取文件的 memeType
        let data = fs.readFileSync(filePath);// 读取文件数据
        data = new Buffer(data).toString('base64'); // 转化 base64s
        this.logs(`图片地址为 :: ${data}`)
        return await postBJ(API.FACE, {
            baseImage:data,
            course_id,
            unit_id,
            class_id
        }, this.getHeaders())
    },
    async getUnitInfo(course_id,class_id,unit_id){
        let param = this.getHeaders();
        param.params = {
            course_id,
            class_id
        }
        return await getBJ(API.UNIT_INFO + unit_id, param)
    },
    async startLearn(){
        let data = this.unitList[this.learnIndex];
        this.logs(`--课程名字----${data.course_title}---开始学习单元【${data.unit_title}】`)
        if(!data){
            this.logs(`已经全部学习完成`)
            return false
        }
        // 要学习时间与已经学习时间相同 跳过当前单元学习
        if(data.time == data.progress_time){
            await this.nextUnit(data)
            return false
        }
        await this.againLearn(data)
    },
    async nextUnit(data){
        ++ this.learnIndex;
        if(this.unitList.length -1 < this.learnIndex){
            this.logs(`已经全部学习完成`)
            return false
        }
        this.logs(`单元【${data.unit_title}】学习完毕`)
        await this.startLearn();
    },
    async againLearn(data){
        // 间隔 60 秒
        let time = 60;
        if (data.progress_time == 0) {
            time = 0;
        }
        if (data.progress_time == 1) {
            time = 59;
        }
        // 是否结束标记
        let isEnd = false;
        if(data.time - data.progress_time < 60){
            time = data.time - data.progress_time;
            isEnd = true
        }
        let progressTime = Number(data.progress_time) + Number(time)
        // 上报学习记录
        let res = await this.studies(data.class_id, data.course_id, data.unit_id, data.video_id, progressTime, isEnd );
        if(!res.code && !isEnd){
            data.progress_time = Number(progressTime) || 1;
            this.logs(`--课程名字----${data.course_title}--单元【${data.unit_title}】学习进度 ${data.progress_time}/${data.time}`)
            await wait(60);
            await this.againLearn(data);
        }
        // 开始下一单元学习
        else{
            await this.nextUnit(data)
        }
    },
    logs(msg){
        let time = new Date();
        let timeSign = time.getTime();
        let year = time.getFullYear();
        let month = time.getMonth() + 1;
        let date = time.getDate();
        console.log(`${this.userLoginInfo.username}-----${msg}-----------${year}--${month}--${date}--${timeSign}`);
        this.logger.log( `${this.userLoginInfo.username}-----${msg}-----------${year}--${month}--${date}--${timeSign}`);
    },
    async testAPI(){
        let res = await getBJ(API.CODE,this.getHeaders());
        let res1 = await getBJ("http://10.10.18.245:8888/digit/recognition/get?imageBase64="+res.data)
        console.log(res.data);
        console.log(res1.data.result);
    },
}

/** 用户数组 */
let users = require("./user.js")
users.forEach(user=>{
    let options = {
        flags: 'w', //
        encoding: 'utf8', // utf8编码
    }
    let stderr = fs.createWriteStream(`./${user.username}-${new Date().getTime()}-junxunding.log`, options);
    let logger = new console.Console(stderr);
    logger.log("分割线================================分割线")
    new start(user, logger)
})


